import os
import logging
from typing import Dict, List, Optional, Any, Generator, AsyncGenerator
import json
import asyncio
from datetime import datetime


class SimpleAgent:
    def __init__(self, upload_manager=None):
        self.logger = logging.getLogger(__name__)
        self.session_histories = {}
        
        # 流式处理相关
        self._stop_flags = {}  # 存储每个会话的停止标志
        self._lock = asyncio.Lock()  # 异步锁

        # 延迟初始化各个组件
        self.llm = None
        self.file_tool = None
        self.web_browser = None
        self.upload_manager = upload_manager

        # 初始化状态
        self.components_initialized = False

        # 命令映射
        self.commands = {
            "/files": self._handle_list_files,
            "/read": self._handle_read_file,
            "/write": self._handle_write_file,
            "/info": self._handle_file_info,
            "/uploads": self._handle_list_uploads,
            "/use": self._handle_use_file,
            "/unuse": self._handle_unuse_file,
            "/using": self._handle_list_using_files,
            "/delete_upload": self._handle_delete_upload,
            "/clear_uploads": self._handle_clear_uploads,
            "/browse": self._handle_web_browse,
            "/run_code": self._handle_run_code,  # 代码执行命令
            # "/debug_code": self._handle_debug_code,  # 代码调试命令 - 现在在process_message_stream中特殊处理
            "/help": self._handle_help
        }

        # 尝试初始化组件（在异步环境中需要手动调用）
        # self._initialize_components() # 将在第一次使用时异步初始化

    async def _initialize_components(self):
        """延迟初始化各个组件，避免一个失败影响全部"""
        try:
            # 1. 初始化LLM客户端
            try:
                from llm.async_ollama_client import AsyncOllamaClient
                self.llm = AsyncOllamaClient()
                self.logger.info("✅ LLM客户端初始化成功")
            except Exception as e:
                self.llm = None  # 确保设置为None
                self.logger.warning(f"❌ LLM客户端初始化失败: {e}")

            # 2. 初始化文件工具
            try:
                from tools.file_tool import FileTool
                self.file_tool = FileTool()
                self.logger.info("✅ 文件工具初始化成功")
            except Exception as e:
                self.logger.warning(f"❌ 文件工具初始化失败: {e}")

            # 3. 初始化网页浏览器
            try:
                from tools.web_browser_tool import WebBrowserTool
                from tools.enhanced_web_browser_tool import EnhancedWebBrowserTool
                
                # 使用更保守的初始化参数
                base_browser = WebBrowserTool(headless=True, max_retries=2)
                
                # 创建增强版网页浏览器工具，只有在LLM可用时才使用
                if hasattr(self, 'llm') and self.llm is not None:
                    self.web_browser = EnhancedWebBrowserTool(base_browser, self.llm)
                else:
                    self.web_browser = base_browser
                self.base_web_browser = base_browser  # 保留基础版本的引用
                
                if base_browser.initialized:
                    self.logger.info("✅ 增强版网页浏览器初始化成功")
                else:
                    self.logger.warning("🔄 增强版网页浏览器使用模拟模式")
            except Exception as e:
                self.logger.warning(f"❌ 网页浏览器初始化失败: {e}")
                # 如果增强版失败，回退到基础版
                try:
                    from tools.web_browser_tool import WebBrowserTool
                    self.web_browser = WebBrowserTool(headless=True, max_retries=2)
                    self.base_web_browser = self.web_browser
                    self.logger.info("✅ 基础网页浏览器初始化成功（回退模式）")
                except Exception as e2:
                    self.web_browser = None  # 确保设置为None
                    self.base_web_browser = None
                    self.logger.warning(f"❌ 基础网页浏览器也初始化失败: {e2}")

            # 4. 初始化上传管理器（如果upload_manager为空，才创建新实例）
            if self.upload_manager is None:
                try:
                    from tools.upload_manager import UploadManager
                    self.upload_manager = UploadManager()
                    self.logger.info("✅ 上传管理器初始化成功（新建实例）")
                except Exception as e:
                    self.logger.warning(f"❌ 上传管理器初始化失败: {e}")
            else:
                self.logger.info("✅ 使用传入的上传管理器实例")

            self.components_initialized = True
            self.logger.info("🎉 智能体所有组件初始化完成")
            
            # 5. 清理临时文件夹
            self._cleanup_temp_directory()

        except Exception as e:
            self.logger.error(f"💥 智能体初始化严重错误: {e}")

    def _cleanup_temp_directory(self):
        """清理临时文件夹，系统启动时调用"""
        try:
            import os
            import shutil
            # 使用 FileTool 的 workspace_dir 来构建完整路径
            temp_dir = os.path.join(self.file_tool.workspace_dir, "temp")
            
            if os.path.exists(temp_dir):
                # 删除整个临时目录
                shutil.rmtree(temp_dir)
                self.logger.info(f"🧹 已清理临时目录：{temp_dir}")
            
            # 重新创建空的临时目录
            os.makedirs(temp_dir, exist_ok=True)
            self.logger.info(f"📁 已重新创建临时目录：{temp_dir}")
            
        except Exception as e:
            self.logger.warning(f"⚠️ 清理临时目录失败：{e}")

    async def process_message_stream(self, user_input: str, session_id: str = "default"):
        """处理用户输入 - 流式输出版本（优化停止检查）"""
        # 确保组件已初始化
        if not self.components_initialized:
            await self._initialize_components()

        # 初始化会话历史
        if session_id not in self.session_histories:
            self.session_histories[session_id] = []

        history = self.session_histories[session_id]
        history.append({"role": "user", "content": user_input})

        # 重置停止标志 - 确保新对话开始时清理停止状态
        async with self._lock:
            self._stop_flags[session_id] = False
        
        # 同时清理LLM和浏览器工具的停止标志
        if self.llm is not None and hasattr(self.llm, 'clear_stop_flag'):
            await self.llm.clear_stop_flag(session_id)
        if self.web_browser is not None and hasattr(self.web_browser, 'clear_stop_flag'):
            self.web_browser.clear_stop_flag(session_id)

        # 1. 检查是否为命令
        if user_input.strip().startswith("/smart_search"):
            # 特殊处理智能搜索命令，使用流式输出
            async for chunk in self._handle_smart_search_stream(user_input, session_id):
                yield chunk
            return
        
        if user_input.strip().startswith("/generate_code"):
            # 特殊处理代码生成命令，使用流式输出
            async for chunk in self._handle_generate_code_stream(user_input, session_id):
                yield chunk
            return
        
        if user_input.strip().startswith("/debug_code"):
            # 特殊处理代码调试命令，使用异步处理
            try:
                response = await self._handle_debug_code(user_input, session_id)
                history.append({"role": "assistant", "content": response})
                yield response
                return
            except Exception as e:
                error_msg = f"❌ 调试命令执行失败：{str(e)}"
                history.append({"role": "assistant", "content": error_msg})
                yield error_msg
                return
        
        # 2. 检查其他命令
        response = self._process_command(user_input, session_id)
        if response:
            history.append({"role": "assistant", "content": response})
            yield response
            return

        # 2. 检查是否有要使用的文件
        files_to_use = self.upload_manager.get_files_to_use(session_id)

        # 处理前检查停止
        async with self._lock:
            if self._stop_flags.get(session_id, False):
                yield "⏹️ 处理已被用户停止"
                return

        if files_to_use:
            # 处理包含文件的消息 - 流式版本
            async for chunk in self._handle_message_with_files_stream(user_input, files_to_use, session_id, history):
                # 在每个chunk后检查停止
                async with self._lock:
                    if self._stop_flags.get(session_id, False):
                        yield "⏹️ 处理已被用户停止"
                        return
                yield chunk
            # 使用后重置文件状态
            self.upload_manager.reset_used_files(session_id)
            return

        # 3. 智能意图识别 - 自动搜索触发
        search_intent = self._detect_search_intent(user_input)
        if search_intent:
            # 自动触发智能搜索
            yield f"🤖 检测到搜索意图：{search_intent['description']}\n"
            yield f"🔍 正在自动搜索：{search_intent['query']}\n\n"
            
            # 执行智能搜索
            async for chunk in self._handle_smart_search_stream(f"/smart_search {search_intent['query']}", session_id):
                yield chunk
            return

        # 4. 智能意图识别 - 自动代码生成触发
        code_intent = self._detect_code_generation_intent(user_input)
        if code_intent:
            # 自动触发代码生成
            yield f"🤖 检测到代码生成意图：{code_intent['description']}\n"
            yield f"💻 正在自动生成代码：{code_intent['requirement']}\n\n"
            
            # 执行代码生成
            async for chunk in self._handle_generate_code_stream(f"/generate_code {code_intent['requirement']}", session_id):
                yield chunk
            return

        # 5. 普通消息处理 - 流式版本
        if self.llm is not None and await self.llm.is_available():
            full_response = ""
            try:
                # 使用流式聊天功能
                stream_generator = None
                if hasattr(self.llm, 'chat_stream_with_history') and len(history) > 1:
                    print(f"[DEBUG] 使用chat_stream_with_history，历史记录长度: {len(history)}")
                    # 注意：这里不需要await，因为chat_stream_with_history返回的是AsyncGenerator
                    stream_generator = self.llm.chat_stream_with_history(history, session_id)
                elif hasattr(self.llm, 'chat_stream'):
                    print(f"[DEBUG] 使用chat_stream")
                    # 注意：这里不需要await，因为chat_stream返回的是AsyncGenerator
                    stream_generator = self.llm.chat_stream(user_input, session_id)
                
                print(f"[DEBUG] stream_generator类型: {type(stream_generator)}")
                if stream_generator is not None:
                    # 处理流式输出
                    try:
                        async for chunk in stream_generator:
                            # 在每个chunk前后都检查停止标志
                            async with self._lock:
                                if self._stop_flags.get(session_id, False):
                                    # 如果被停止，添加停止消息到历史记录
                                    if full_response:
                                        history.append({"role": "assistant", "content": full_response + "\n⏹️ 生成已被用户停止"})
                                    else:
                                        history.append({"role": "assistant", "content": "⏹️ 生成已被用户停止"})
                                    yield "\n⏹️ 生成已被用户停止"
                                    return

                            full_response += chunk
                            yield chunk

                            # 再次检查停止标志
                            async with self._lock:
                                if self._stop_flags.get(session_id, False):
                                    # 如果被停止，添加停止消息到历史记录
                                    if full_response:
                                        history.append({"role": "assistant", "content": full_response + "\n⏹️ 生成已被用户停止"})
                                    else:
                                        history.append({"role": "assistant", "content": "⏹️ 生成已被用户停止"})
                                    yield "\n⏹️ 生成已被用户停止"
                                    return
                    except Exception as stream_error:
                        print(f"[DEBUG] 流式处理异常: {type(stream_error).__name__}: {str(stream_error)}")
                        # 如果流式处理失败，回退到非流式
                        if hasattr(self.llm, 'chat'):
                            response = await self.llm.chat(user_input, session_id)
                            full_response = response
                            yield response
                        else:
                            yield f"处理消息时出错: {str(stream_error)}"
                else:
                    print(f"[DEBUG] stream_generator为None，回退到非流式")
                    # 回退到非流式
                    if hasattr(self.llm, 'chat'):
                        response = await self.llm.chat(user_input, session_id)
                        full_response = response
                        yield response
                    else:
                        yield "LLM服务不可用"

                # 添加到历史记录（只有在没有被停止的情况下）
                if full_response and not self._stop_flags.get(session_id, False):
                    history.append({"role": "assistant", "content": full_response})

            except Exception as e:
                print(f"[DEBUG] 异常详情: {type(e).__name__}: {str(e)}")
                import traceback
                print(f"[DEBUG] 异常堆栈: {traceback.format_exc()}")
                error_msg = f"处理消息时出错: {str(e)}"
                history.append({"role": "assistant", "content": error_msg})
                yield error_msg
        else:
            print(f"[DEBUG] LLM不可用，llm={self.llm}, is_available={await self.llm.is_available() if self.llm else 'N/A'}")
            response = "LLM服务暂不可用。"
            history.append({"role": "assistant", "content": response})
            yield response

    async def _handle_message_with_files_stream(self, user_input: str, files_to_use: List[Dict], 
                                        session_id: str, history: List[Dict]):
        """处理包含文件的消息 - 流式版本"""
        try:
            print(f"[DEBUG] 开始处理文件，文件数量: {len(files_to_use)}")
            
            # 解析文件内容
            file_contents = []
            unsupported_files = []
            
            for file_info in files_to_use:
                try:
                    print(f"[DEBUG] 处理文件: {file_info['original_name']}")
                    file_id = file_info['id']
                        
                    content = self.upload_manager.read_file_content(session_id, file_id)
                    if content:
                        file_contents.append({
                            'name': file_info['original_name'],
                            'content': content
                        })
                    else:
                        unsupported_files.append({
                            'name': file_info['original_name'],
                            'error': '文件格式不支持或解析失败'
                        })
                except Exception as e:
                    print(f"[DEBUG] 解析文件 {file_info} 失败: {e}")

            # 构建提示词
            prompt = f"用户问题: {user_input}\n\n"
            
            if file_contents:
                prompt += "相关文件内容:\n"
                for file in file_contents:
                    prompt += f"\n--- {file['name']} ---\n"
                    prompt += file['content'][:10000]  # 限制单个文件内容长度
                    if len(file['content']) > 10000:
                        prompt += "\n[内容过长，已截断...]"
                    prompt += "\n"

            if unsupported_files:
                prompt += "\n无法解析的文件:\n"
                for file in unsupported_files:
                    prompt += f"• {file['name']}: {file['error']}\n"

            # 使用LLM处理 - 流式版本
            if self.llm and await self.llm.is_available():
                full_response = ""
                try:
                    # 构建包含历史上下文的完整提示词
                    stream_generator = None
                    if hasattr(self.llm, 'chat_stream_with_history') and len(history) > 1:
                        # 将文件处理提示添加到历史中
                        temp_history = history.copy()
                        temp_history.append({"role": "user", "content": prompt})
                        stream_generator = self.llm.chat_stream_with_history(temp_history, session_id)
                    elif hasattr(self.llm, 'chat_stream'):
                        stream_generator = self.llm.chat_stream(prompt, session_id)
                    
                    if stream_generator is not None:
                        async for chunk in stream_generator:
                            # 检查停止标志
                            async with self._lock:
                                if self._stop_flags.get(session_id, False):
                                    # 如果被停止，添加停止消息到历史记录
                                    if full_response:
                                        history.append({"role": "assistant", "content": full_response + "\n⏹️ 生成已被用户停止"})
                                    else:
                                        history.append({"role": "assistant", "content": "⏹️ 生成已被用户停止"})
                                    yield "\n⏹️ 生成已被用户停止"
                                    return
                            full_response += chunk
                            yield chunk
                            
                            # 再次检查停止标志
                            async with self._lock:
                                if self._stop_flags.get(session_id, False):
                                    # 如果被停止，添加停止消息到历史记录
                                    if full_response:
                                        history.append({"role": "assistant", "content": full_response + "\n⏹️ 生成已被用户停止"})
                                    else:
                                        history.append({"role": "assistant", "content": "⏹️ 生成已被用户停止"})
                                    yield "\n⏹️ 生成已被用户停止"
                                    return
                    else:
                        # 回退到非流式
                        response = await self.llm.chat(prompt, session_id)
                        full_response = response
                        yield response
                    
                    # 记录到历史
                    if full_response:
                        file_names = ", ".join([file['name'] for file in file_contents])
                        if unsupported_files:
                            skipped_names = ", ".join([file['name'] for file in unsupported_files])
                            file_names += f" (跳过: {skipped_names})"
                        
                        history.append({
                            "role": "system",
                            "content": f"使用文件: {file_names}, 用户要求: {user_input}"
                        })
                        history.append({"role": "assistant", "content": full_response})
                        
                except Exception as e:
                    error_msg = f"处理文件时出错: {str(e)}"
                    history.append({"role": "assistant", "content": error_msg})
                    yield error_msg
            else:
                error_msg = "LLM服务暂不可用，无法处理文件。"
                yield error_msg

        except Exception as e:
            self.logger.error(f"处理文件时出错: {e}")
            error_msg = f"❌ 处理文件时出错：{str(e)}"
            yield error_msg

    async def stop_generation(self, session_id: str) -> bool:
        """停止指定会话的生成"""
        try:
            async with self._lock:
                self._stop_flags[session_id] = True
            
            # 同时停止LLM的生成
            llm_stopped = True
            if self.llm and hasattr(self.llm, 'stop_generation'):
                try:
                    result = self.llm.stop_generation(session_id)
                    if result is not None and hasattr(result, '__await__'):
                        await result
                    self.logger.info(f"LLM停止生成成功: {session_id}")
                except Exception as e:
                    self.logger.error(f"LLM停止生成失败: {e}")
                    llm_stopped = False
            
            # 更新智能体的停止方法，确保同时停止增强版网页浏览器
            browser_stopped = True
            if self.web_browser and hasattr(self.web_browser, 'stop_generation'):
                try:
                    browser_stopped = self.web_browser.stop_generation(session_id)
                    self.logger.info(f"浏览器停止生成成功: {session_id}")
                except Exception as e:
                    self.logger.error(f"浏览器停止生成失败: {e}")
                    browser_stopped = False
            
            # 清理停止标志，避免影响下次对话
            await asyncio.sleep(0.1)  # 短暂等待确保停止操作完成
            async with self._lock:
                if session_id in self._stop_flags:
                    del self._stop_flags[session_id]
            
            return llm_stopped and browser_stopped
        except Exception as e:
            self.logger.error(f"停止生成失败: {e}")
            return False

    async def stop_all_generations(self) -> bool:
        """停止所有活跃的生成"""
        try:
            async with self._lock:
                for session_id in self._stop_flags:
                    self._stop_flags[session_id] = True
            
            # 同时停止LLM的所有生成
            llm_stopped = True
            if self.llm and hasattr(self.llm, 'stop_all_generations'):
                llm_stopped = await self.llm.stop_all_generations()
            
            # 停止网页浏览器的所有搜索
            browser_stopped = True
            if hasattr(self.web_browser, 'stop_all_generations'):
                browser_stopped = self.web_browser.stop_all_generations()
            
            return llm_stopped and browser_stopped
        except Exception as e:
            self.logger.error(f"停止所有生成失败: {e}")
            return False

    def _process_command(self, user_input: str, session_id: str) -> Optional[str]:
        """处理命令"""
        if not hasattr(self, 'commands') or not self.commands:
            return None

        for cmd, handler in self.commands.items():
            if user_input.startswith(cmd) and handler is not None:
                try:
                    # 直接调用处理器，只传递两个参数
                    return handler(user_input, session_id)
                except TypeError as e:
                    self.logger.error(f"命令处理错误 {cmd}: {e}")
                    return f"命令处理错误: {cmd}"
        return None

    def _detect_code_generation_intent(self, user_input: str) -> dict:
        """
        简化的代码生成意图检测 - 只要有关键词就判断为代码生成
        
        Args:
            user_input: 用户输入的消息
            
        Returns:
            如果检测到代码生成意图，返回包含需求和描述的字典；否则返回None
        """
        user_input_lower = user_input.lower()
        
        # 所有代码生成关键词
        code_keywords = [
            # 直接代码生成
            "生成代码", "生成", "编写", "编写代码", "generate code", "write code", "create code",
            # 算法相关
            "算法", "排序", "动态规划", "贪心", "递归", "algorithm", "sort", "dp", "dynamic programming", "greedy", "recursive",
            # 数据结构
            "数据结构", "链表", "栈", "队列", "树", "图", "哈希表", "data structure", "linked list", "stack", "queue", "tree", "graph", "hash table",
            # 功能实现
            "实现", "创建", "做一个", "写一个", "开发", "implement", "create", "make", "build", "develop",
            # 工具脚本
            "脚本", "工具", "爬虫", "计算器", "转换器", "script", "tool", "crawler", "calculator", "converter",
            # 面向对象
            "类", "对象", "class", "object", "面向对象", "oop",
            # 编程语言
            "python", "函数", "function", "def", "方法", "method", "代码", "code"
        ]
        
        # 检查是否包含任何代码生成关键词
        if any(keyword in user_input_lower for keyword in code_keywords):
            return {
                "requirement": user_input.strip(),
                "description": "代码生成",
                "confidence": 0.8
            }
        
        return None

    async def _handle_message_with_files(self, user_input: str, files_to_use: List[Dict], session_id: str,
                                   history: List) -> str:
        """处理包含文件的消息 - 支持多种文件格式解析"""
        try:
            print(f"[DEBUG] 开始处理包含文件的消息，文件数量: {len(files_to_use)}")
            
            # 读取所有要使用文件的内容
            file_contents = []
            unsupported_files = []
            
            for i, file_info in enumerate(files_to_use):
                print(f"[DEBUG] 处理文件 {i+1}/{len(files_to_use)}: {file_info['original_name']}")
                content = self.upload_manager.read_file_content(session_id, file_info["id"])
                
                if content and not content.startswith("❌"):
                    # 获取文件解析信息
                    parse_info = self.upload_manager.get_file_parse_info(session_id, file_info["id"])
                    
                    file_contents.append({
                        "name": file_info["original_name"],
                        "content": content,
                        "size": file_info["size"],
                        "file_type": parse_info.get("file_extension", "unknown") if parse_info else "unknown",
                        "is_supported": parse_info.get("is_supported", False) if parse_info else False
                    })
                    print(f"[DEBUG] 文件 {file_info['original_name']} 解析成功，内容长度: {len(content)}")
                else:
                    # 记录无法解析的文件
                    unsupported_files.append({
                        "name": file_info["original_name"],
                        "error": content if content else "无法读取文件内容"
                    })
                    print(f"[DEBUG] 文件 {file_info['original_name']} 解析失败: {content}")

            print(f"[DEBUG] 文件处理完成，成功: {len(file_contents)}, 失败: {len(unsupported_files)}")

            # 如果没有可用的文件内容
            if not file_contents:
                error_msg = "❌ 没有可用的文件内容，无法处理请求"
                if unsupported_files:
                    error_msg += "\n\n无法处理的文件："
                    for file in unsupported_files:
                        error_msg += f"\n• {file['name']}: {file['error']}"
                return error_msg

            print(f"[DEBUG] 开始构建LLM提示词...")
            
            # 构建包含文件内容的提示词
            files_description = []
            
            for i, file in enumerate(file_contents):
                file_desc = f"文件 {i + 1}: {file['name']} ({self._format_file_size(file['size'])})"
                
                # 添加文件类型信息
                if file['file_type'] != 'unknown':
                    file_desc += f" [类型: {file['file_type']}]"
                
                # 根据文件大小和类型决定内容截断长度
                max_content_length = self._get_max_content_length(file['file_type'], file['size'])
                content = file['content']
                
                if len(content) > max_content_length:
                    content = content[:max_content_length]
                    file_desc += f"\n内容 (已截断，显示前{max_content_length}字符，完整内容{len(file['content'])}字符):\n```\n{content}\n```"
                else:
                    file_desc += f"\n内容:\n```\n{content}\n```"
                
                files_description.append(file_desc)

            # 构建最终提示词
            prompt = f"""用户提供了 {len(file_contents)} 个文件并请求处理：

{chr(10).join(files_description)}

用户的要求：
{user_input}

请根据这些文件的内容和用户要求进行处理。注意：
1. 文件已经过解析，可以直接分析其中的文本内容
2. 对于表格文件(CSV/Excel)，数据已经格式化为易读的文本形式
3. 对于文档文件(PDF/Word)，文本内容已经提取出来
4. 对于图片文件，提供了基本信息但无法识别图片中的文字
5. 如果内容被截断，请基于可见部分进行分析并说明限制"""

            # 添加不支持文件的提醒
            if unsupported_files:
                prompt += f"\n\n注意：以下文件无法解析，已跳过：\n"
                for file in unsupported_files:
                    prompt += f"• {file['name']}: {file['error']}\n"

            print(f"[DEBUG] 提示词构建完成，长度: {len(prompt)}")
            print(f"[DEBUG] 开始调用LLM...")

            # 使用LLM处理
            if await self.llm.is_available():
                # 构建包含历史上下文的完整提示词
                if hasattr(self.llm, 'chat_with_history') and len(history) > 1:
                    # 将文件处理提示添加到历史中
                    temp_history = history.copy()
                    temp_history.append({"role": "user", "content": prompt})
                    response = await self.llm.chat_with_history(temp_history)
                else:
                    response = await self.llm.chat(prompt)
                
                print(f"[DEBUG] LLM响应完成，响应长度: {len(response)}")

                # 记录到历史
                file_names = ", ".join([file['name'] for file in file_contents])
                if unsupported_files:
                    skipped_names = ", ".join([file['name'] for file in unsupported_files])
                    file_names += f" (跳过: {skipped_names})"
                
                history.append({
                    "role": "system",
                    "content": f"使用文件: {file_names}, 用户要求: {user_input}"
                })
                history.append({"role": "assistant", "content": response})
                print("[DEBUG] 文件处理任务完成")
                return response
            else:
                return "LLM服务暂不可用，无法处理文件。"

        except Exception as e:
            self.logger.error(f"处理文件时出错: {e}")
            print(f"[DEBUG] 处理文件时出错: {e}")
            return f"❌ 处理文件时出错：{str(e)}"

    # 文件操作命令
    def _handle_list_files(self, user_input: str, session_id: str) -> str:
        """处理文件列表命令"""
        directory = user_input.replace("/files", "").strip()
        files = self.file_tool.list_files(directory)
        return "工作目录文件列表：\n" + "\n".join(files)

    def _handle_read_file(self, user_input: str, session_id: str) -> str:
        """处理文件读取命令 - 支持通过文件名自动拼接会话上传路径"""
        # 提取文件名（去除 /read 命令后的所有内容）
        filename = user_input.replace("/read", "").strip()

        if not filename:
            return "请指定要读取的文件名，例如：\n/read example.txt\n/read climb_stairs_dp.py\n/read my_script.py"

        try:
            # 构建会话上传目录的文件路径
            session_upload_dir = self.upload_manager.get_session_upload_dir(session_id)
            
            # 首先尝试直接使用文件名
            filepath = os.path.join(session_upload_dir, filename)
            
            # 如果直接文件名不存在，尝试通过原始文件名查找UUID文件名
            if not os.path.exists(filepath):
                # 获取会话中的所有文件信息
                session_files = self.upload_manager.get_session_files(session_id)
                found_file = None
                
                for file_info in session_files:
                    # 检查原始文件名是否匹配
                    if file_info.get('original_name') == filename:
                        found_file = file_info
                        break
                
                if found_file:
                    # 使用找到的UUID文件名
                    filepath = os.path.join(session_upload_dir, found_file['saved_name'])
                else:
                    # 列出当前会话的所有文件
                    if session_files:
                        file_list = "\n".join([f"- {f.get('original_name', f.get('saved_name', 'unknown'))}" for f in session_files])
                        return f"❌ 文件不存在：{filename}\n\n📁 当前会话中的文件：\n{file_list}\n\n💡 使用 /uploads 查看详细信息"
                    else:
                        return f"❌ 文件不存在：{filename}\n💡 当前会话中没有上传的文件"

            # 直接读取文件内容
            with open(filepath, 'r', encoding='utf-8') as f:
                content = f.read()

            # 限制显示长度，避免返回过长的文件内容
            if len(content) > 2000:
                content = content[:2000] + f"\n\n... (文件内容过长，已截断前2000字符，完整内容共{len(content)}字符)"

            return f"📄 文件内容：{filename}\n\n{content}"

        except Exception as e:
            return f"❌ 读取文件时出错：{str(e)}"

    def _handle_write_file(self, user_input: str, session_id: str) -> str:
        """处理文件写入命令 - 支持文件路径"""
        # 提取命令后的内容
        args = user_input.replace("/write", "").strip()

        if not args:
            return "用法：/write <文件路径> <内容>\n例如：\n/write example.txt Hello World\n/write documents/note.txt 这是一个笔记\n/write /workspace/data/output.txt 这是输出内容"

        try:
            # 查找第一个空格来分割文件路径和内容
            first_space_index = args.find(' ')
            if first_space_index == -1:
                return "❌ 请同时指定文件路径和内容\n用法：/write <文件路径> <内容>"

            # 分割文件路径和内容
            filepath = args[:first_space_index].strip()
            content = args[first_space_index:].strip()

            if not filepath:
                return "❌ 请指定文件路径"
            if not content:
                return "❌ 请指定要写入的内容"

            # 使用文件工具写入文件
            result = self.file_tool.write_file(filepath, content)

            if "成功" in result:
                return f"✅ 文件写入成功：{filepath}\n📝 写入内容长度：{len(content)} 字符"
            else:
                return f"❌ 文件写入失败：{result}"

        except Exception as e:
            return f"❌ 写入文件时出错：{str(e)}"

    def _handle_file_info(self, user_input: str, session_id: str) -> str:
        """处理文件信息命令"""
        filepath = user_input.replace("/info", "").strip()

        if not filepath:
            return "请指定要查看信息的文件路径，例如：\n/info example.txt\n/info documents/data.json"

        try:
            return self.file_tool.get_file_info(filepath)
        except Exception as e:
            return f"❌ 获取文件信息时出错：{str(e)}"


    async def _handle_smart_search_stream(self, user_input: str, session_id: str) -> AsyncGenerator[str, None]:
        """处理智能搜索命令 - 流式版本"""
        query = user_input.replace("/smart_search", "").strip()
        if not query:
            yield "请输入搜索关键词，例如：/smart_search 人工智能发展趋势"
            return

        try:
            # 检查停止标志
            if self._stop_flags.get(session_id, False):
                yield "🛑 智能搜索已被停止"
                return

            # 检查是否有增强版浏览器
            if hasattr(self.web_browser, 'intelligent_search_stream'):
                # 使用流式版本
                final_response = ""
                async for result in self.web_browser.intelligent_search_stream(query, session_id=session_id):
                    # 检查是否被停止
                    if result.get("stopped"):
                        yield "🛑 智能搜索已被停止"
                        return
                    
                    if result.get("error") and not result.get("stopped"):
                        yield f"智能搜索失败：{result['error']}"
                        return
                    
                    # 输出进度信息
                    if "stage" in result and "progress" in result:
                        progress = int(result["progress"])  # 确保progress是整数
                        progress_bar = "█" * (progress // 10) + "░" * (10 - progress // 10)
                        yield f"🔍 {result['stage']} [{progress_bar}] {progress}%\n"
                    
                    # 如果是最终结果（progress = 100 且 status = 完成）
                    if result.get("progress") == 100 and result.get("status") == "完成":
                        # 分段流式输出搜索结果
                        yield f"🧠 智能搜索结果：{query}\n\n"
                        
                        if "summary" in result:
                            yield f"📋 综合摘要：\n{result['summary']}\n\n"
                        
                        if "key_points" in result:
                            yield f"🔑 关键要点：\n"
                            for i, point in enumerate(result['key_points'], 1):
                                yield f"{i}. {point}\n"
                            yield "\n"
                        
                        if "detailed_results" in result:
                            yield f"📊 详细搜索结果：\n"
                            for i, item in enumerate(result['detailed_results'][:5], 1):
                                yield f"{i}. 📄 {item['title']}\n"
                                yield f"   🔗 {item['url']}\n"
                                if 'content_preview' in item:
                                    yield f"   📝 {item['content_preview'][:100]}...\n"
                                yield "\n"
                        
                        if "analysis" in result:
                            yield f"🔍 深度分析：\n{result['analysis']}\n\n"
                        
                        if "recommendations" in result:
                            yield f"💡 相关建议：\n"
                            for rec in result['recommendations']:
                                yield f"• {rec}\n"

                        # 添加到会话历史
                        self.session_histories[session_id].append({
                            "role": "system",
                            "content": f"智能搜索结果：{result}"
                        })

                        return
                
                # 如果没有返回最终结果，说明出现了问题
                if not final_response:
                    yield "智能搜索未能完成，请重试"
                
            else:
                # 回退到基础搜索 - 直接使用增强版浏览器的智能搜索
                yield "🔍 正在进行智能搜索...\n"
                try:
                    result = await self.web_browser.intelligent_search(query, session_id=session_id)
                    if "error" in result:
                        yield f"智能搜索失败：{result['error']}"
                    else:
                        # 格式化结果
                        response = f"🧠 智能搜索结果：{query}\n\n"
                        if "summary" in result:
                            response += f"📋 综合摘要：\n{result['summary']}\n\n"
                        yield response
                except Exception as e:
                    yield f"智能搜索失败：{str(e)}"

        except Exception as e:
            yield f"智能搜索过程中出现错误：{str(e)}"

    # 上传文件管理命令
    def _handle_list_uploads(self, user_input: str, session_id: str) -> str:
        """列出上传的文件"""
        try:
            files = self.upload_manager.get_session_files(session_id)
            if not files:
                return "📁 当前会话没有上传的文件"

            response = "📁 已上传的文件：\n\n"
            using_count = 0

            for i, file_info in enumerate(files, 1):
                status = "✅ 使用中" if file_info.get("used", False) else "⏳ 未使用"
                size_str = self._format_file_size(file_info["size"])

                response += f"{i}. {file_info['original_name']} ({size_str}) - {status}\n"
                response += f"   ID: {file_info['id']}\n"

                if file_info.get("used", False):
                    using_count += 1

            response += f"\n💡 共 {len(files)} 个文件，其中 {using_count} 个标记为使用中"
            response += "\n🔧 使用 /use <文件ID> 标记文件为使用中"
            response += "\n🔧 使用 /unuse <文件ID> 取消使用标记"
            response += "\n🔧 使用 /using 查看使用中的文件"
            response += "\n🗑️ 使用 /delete_upload <文件ID> 删除文件"
            response += "\n🧹 使用 /clear_uploads 清空所有文件"

            return response

        except Exception as e:
            return f"❌ 列出上传文件时出错：{str(e)}"

    def _handle_use_file(self, user_input: str, session_id: str) -> str:
        """标记文件为使用中"""
        try:
            file_id = user_input.replace("/use", "").strip()
            if not file_id:
                return "❌ 请指定要使用的文件ID，使用 /uploads 查看文件列表"

            file_info = self.upload_manager.get_file_info(session_id, file_id)
            if not file_info:
                return f"❌ 文件不存在: {file_id}"

            success = self.upload_manager.mark_file_for_use(session_id, file_id)
            if success:
                return f"✅ 文件已标记为使用中: {file_info['original_name']}\n💡 下次发送消息时，这个文件会自动加入对话"
            else:
                return f"❌ 标记文件失败: {file_info['original_name']}"

        except Exception as e:
            return f"❌ 标记文件时出错：{str(e)}"

    def _handle_unuse_file(self, user_input: str, session_id: str) -> str:
        """取消文件的使用标记"""
        try:
            file_id = user_input.replace("/unuse", "").strip()
            if not file_id:
                return "❌ 请指定要取消使用的文件ID，使用 /using 查看使用中的文件"

            file_info = self.upload_manager.get_file_info(session_id, file_id)
            if not file_info:
                return f"❌ 文件不存在: {file_id}"

            success = self.upload_manager.unmark_file_for_use(session_id, file_id)
            if success:
                return f"✅ 已取消文件的使用标记: {file_info['original_name']}"
            else:
                return f"❌ 取消文件标记失败: {file_info['original_name']}"

        except Exception as e:
            return f"❌ 取消文件标记时出错：{str(e)}"

    def _handle_list_using_files(self, user_input: str, session_id: str) -> str:
        """列出使用中的文件"""
        print("用户id:" + session_id)
        try:
            using_files = self.upload_manager.get_files_to_use(session_id)
            if not using_files:
                return "📝 当前没有标记为使用中的文件\n💡 使用 /use <文件ID> 来标记文件"

            response = "🔄 使用中的文件（将在下次对话时自动加入上下文）：\n\n"

            for i, file_info in enumerate(using_files, 1):
                size_str = self._format_file_size(file_info["size"])
                response += f"{i}. {file_info['original_name']} ({size_str})\n"
                response += f"   ID: {file_info['id']}\n"

            response += f"\n💡 共 {len(using_files)} 个文件等待使用"
            response += "\n🗑️ 使用 /unuse <文件ID> 取消使用标记"
            response += "\n📝 发送任意消息即可使用这些文件"

            return response

        except Exception as e:
            return f"❌ 列出使用中文件时出错：{str(e)}"

    def _handle_delete_upload(self, user_input: str, session_id: str) -> str:
        """删除上传的文件"""
        try:
            file_id = user_input.replace("/delete_upload", "").strip()
            if not file_id:
                return "❌ 请指定要删除的文件ID，使用 /uploads 查看文件列表"

            success = self.upload_manager.delete_file(session_id, file_id)
            if success:
                return f"✅ 文件已删除"
            else:
                return f"❌ 文件不存在或删除失败"

        except Exception as e:
            return f"❌ 删除文件时出错：{str(e)}"

    def _handle_clear_uploads(self, user_input: str, session_id: str) -> str:
        """清空所有上传文件"""
        try:
            success = self.upload_manager.clear_session_files(session_id)
            if success:
                return "✅ 所有上传文件已清空"
            else:
                return "❌ 清空文件失败"
        except Exception as e:
            return f"❌ 清空文件时出错：{str(e)}"

    def _handle_web_browse(self, user_input: str, session_id: str) -> str:
        """处理网页浏览命令"""
        url = user_input.replace("/browse", "").strip()
        if not url:
            return "请指定要浏览的网址，例如：/browse https://example.com"

        # 确保URL有协议前缀
        if not url.startswith(('http://', 'https://')):
            url = 'https://' + url

        try:
            result = self.web_browser.get_page_content(url)

            if "error" in result:
                return f"浏览网页失败：{result['error']}"

            # 格式化网页内容
            response = f"🌐 网页内容：{result['title']}\n"
            response += f"📎 网址：{result['url']}\n\n"
            response += f"📄 内容摘要：\n{result['content'][:500]}..."

            if len(result['content']) > 500:
                response += f"\n\n(内容截断，完整内容约{len(result['content'])}字符)"

            # 添加到会话历史
            self.session_histories[session_id].append({
                "role": "system",
                "content": f"网页内容：{result}"
            })

            return response

        except Exception as e:
            return f"浏览网页过程中出现错误：{str(e)}"

    def _handle_help(self, user_input: str, session_id: str) -> str:
        """处理帮助命令"""
        # 获取支持的文件类型
        supported_types = self.upload_manager.get_supported_file_types()
        
        return f"""
🤖 AgenticSeek 智能体系统 - 完整功能帮助 (会话: {session_id})

🧠 智能意图识别：
• 自动检测搜索意图 - 无需输入命令，直接说"搜索人工智能"或"了解Python"
• 自动检测代码生成意图 - 直接说"生成一个背包算法"或"创建计算器类"
• 智能上下文理解 - 根据对话历史提供个性化响应

📁 文件操作命令：
/files [目录] - 列出工作目录文件
/read <文件> - 读取文件内容
/write <文件> <内容> - 写入文件
/info <文件> - 获取文件信息

📤 上传文件管理：
/uploads - 列出所有上传的文件
/use <文件ID> - 标记文件为使用中
/unuse <文件ID> - 取消文件使用标记  
/using - 查看使用中的文件
/delete_upload <文件ID> - 删除上传的文件
/clear_uploads - 清空所有上传文件

🌐 网页浏览与搜索：
/smart_search <关键词> - 智能搜索（AI深度分析汇总）
/browse <网址> - 浏览指定网页内容

💻 代码执行与调试：
/run_code <文件名> - 执行Python代码文件（支持会话文件自动路径解析）
/debug_code <文件名> - 分析和调试Python代码（AI智能错误分析）
/generate_code <需求> - 根据需求生成Python代码（流式输出）

⏹️ 流程控制：
/stop - 停止当前正在执行的任务（搜索、代码生成等）
• 支持实时停止长时间运行的智能搜索
• 支持停止代码生成过程
• 支持停止网页浏览任务

📋 支持的文件格式：
• 文本文件: .txt, .md, .py, .js, .java, .cpp, .c, .html, .css, .json, .xml
• 表格文件: .csv, .xlsx, .xls  
• 文档文件: .pdf, .docx, .doc
• 图片文件: .jpg, .jpeg, .png, .gif, .bmp

🔄 智能文件使用流程：
1. 上传文件 → 自动解析并标记为未使用
2. 使用 /use <文件ID> → 标记文件为使用中
3. 发送任何消息 → 使用中的文件自动加入AI上下文
4. 处理完成后 → 文件自动重置为未使用状态

🚀 智能交互示例：

📝 自然语言交互：
"搜索最新的AI发展趋势"        → 自动触发智能搜索
"生成一个背包问题算法"        → 自动生成代码并保存
"了解Python装饰器"          → 自动搜索并分析相关内容
"比较React和Vue的优缺点"     → 自动搜索并对比分析

📋 命令式操作：
/uploads                        → 查看所有上传文件
/use abc123def                  → 标记文件为使用中
/using                          → 查看当前使用中的文件
"请分析这些代码的性能问题"       → AI分析使用中的文件
/generate_code 创建REST API     → 生成API代码
/run_code knapsack_01.py        → 执行代码文件
/debug_code knapsack_01.py      → 调试分析代码

🔍 智能搜索流程：
1. "搜索机器学习算法" → 自动触发智能搜索
2. 系统并发抓取多个相关网页
3. AI深度分析内容并生成摘要
4. 提供关键要点和相关建议
5. 支持随时使用 /stop 停止搜索

💻 代码执行与调试流程：
1. "生成一个排序算法" → AI自动生成代码并保存
2. /run_code generated_code_xxx.py → 执行代码查看结果  
3. /debug_code generated_code_xxx.py → 如有错误，获取AI调试分析
4. 根据调试建议修改代码 → 使用 /write 保存修复版本
5. /run_code generated_code_xxx.py → 重新测试验证

🎯 系统特色功能：
• 🧠 智能意图识别 - 无需记忆复杂命令
• 🔄 流式响应 - 实时显示处理进度
• ⏹️ 随时停止 - 可中断长时间任务
• 📁 智能文件管理 - 自动上下文集成和路径解析
• 🌐 并发网页抓取 - 快速获取信息
• 💻 代码执行调试 - 完整开发流程支持
• 🔒 会话隔离 - 多用户安全使用
• 🛠️ 错误修复 - 路径重复拼接问题已解决

💡 使用提示：
• 代码执行命令支持原始文件名和UUID文件名自动识别
• 文件路径自动解析，无需手动拼接完整路径
• /debug_code 提供AI智能错误分析和修复建议
• 文件标记为used=True时会自动加入下次对话上下文
• 文件使用后自动重置，支持重复使用
• 支持同时使用多个文件进行分析
• 智能搜索支持中英文关键词
• 代码生成支持多种编程语言需求描述
• 所有长时间任务都支持 /stop 命令中断
• 系统会自动解析不同格式的文件内容
• PDF、Word、Excel等文件会被转换为文本格式
• 图片文件会提供基本信息（尺寸、格式等）

🔧 最新修复：
• ✅ 修复了 /run_code 和 /debug_code 命令的路径重复拼接问题
• ✅ 修复了 FastAPI 序列化错误和 logger 导入问题
• ✅ 优化了异步命令处理机制
• ✅ 改进了错误处理和用户反馈
"""

    def _format_file_size(self, size_bytes: int) -> str:
        """格式化文件大小"""
        if size_bytes < 1024:
            return f"{size_bytes} B"
        elif size_bytes < 1024 * 1024:
            return f"{size_bytes / 1024:.1f} KB"
        else:
            return f"{size_bytes / 1024 / 1024:.1f} MB"



    def get_session_history(self, session_id: str):
        """获取会话历史"""
        return self.session_histories.get(session_id, [])

    def clear_session(self, session_id: str):
        """清除会话历史"""
        if session_id in self.session_histories:
            del self.session_histories[session_id]

    def clear_incomplete_message(self, session_id: str):
        """清理会话中未完成的消息（通常是最后一条助手消息）"""
        if session_id in self.session_histories:
            history = self.session_histories[session_id]
            # 如果最后一条消息是助手消息且内容为空或只有空白字符，则删除它
            if history and history[-1].get("role") == "assistant":
                content = history[-1].get("content", "").strip()
                if not content:
                    history.pop()
                    self.logger.info(f"已清理会话 {session_id} 中的未完成消息")

    def clear_last_conversation_round(self, session_id: str):
        """清除会话中的最后一轮对话（包括用户问题和助手回复）"""
        if session_id in self.session_histories:
            history = self.session_histories[session_id]
            messages_removed = 0
            
            # 从后往前检查并删除最后的助手消息和用户消息
            if history and history[-1].get("role") == "assistant":
                history.pop()
                messages_removed += 1
                self.logger.info(f"已删除会话 {session_id} 中的最后一条助手消息")
            
            # 检查并删除最后的用户消息
            if history and history[-1].get("role") == "user":
                history.pop()
                messages_removed += 1
                self.logger.info(f"已删除会话 {session_id} 中的最后一条用户消息")
            
            if messages_removed > 0:
                self.logger.info(f"已从会话 {session_id} 中清除最后一轮对话，删除了 {messages_removed} 条消息")

    def _get_max_content_length(self, file_type: str, file_size: int) -> int:
        """根据文件类型和大小决定最大内容长度"""
        # 基础长度限制
        base_limits = {
            '.txt': 8000,
            '.md': 8000,
            '.py': 6000,
            '.js': 6000,
            '.java': 6000,
            '.cpp': 6000,
            '.c': 6000,
            '.html': 5000,
            '.css': 4000,
            '.json': 5000,
            '.xml': 5000,
            '.csv': 10000,  # 表格数据可能需要更多空间
            '.xlsx': 10000,
            '.xls': 10000,
            '.pdf': 12000,  # PDF提取的文本可能较长
            '.docx': 10000,
            '.doc': 10000,
            # 图片文件通常只有基本信息，不需要太多空间
            '.jpg': 1000,
            '.jpeg': 1000,
            '.png': 1000,
            '.gif': 1000,
            '.bmp': 1000,
        }
        
        # 获取基础限制
        max_length = base_limits.get(file_type, 5000)  # 默认5000字符
        
        # 根据文件大小调整
        if file_size < 10 * 1024:  # 小于10KB
            return max_length
        elif file_size < 100 * 1024:  # 小于100KB
            return int(max_length * 1.2)
        elif file_size < 1024 * 1024:  # 小于1MB
            return int(max_length * 1.5)
        else:  # 大于1MB
            return int(max_length * 2)

    def _detect_search_intent(self, user_input: str) -> dict:
        """
        简化的搜索意图检测 - 只要有关键词就判断为智能搜索
        
        Args:
            user_input: 用户输入的消息
            
        Returns:
            如果检测到搜索意图，返回包含查询和描述的字典；否则返回None
        """
        user_input_lower = user_input.lower()
        
        # 所有搜索关键词
        search_keywords = [
            # 直接搜索
            "搜索", "查找", "找", "search", "find", "look up",
            # 学习了解
            "了解", "学习", "什么是", "介绍", "explain", "learn about", "understand",
            # 技能需求
            "需要哪些技能", "技能要求", "技术栈", "需要学什么", "skills needed", "requirements",
            # 比较选择
            "比较", "对比", "哪个更好", "选择", "compare", "vs", "versus", "difference",
            # 最新趋势
            "最新", "新版本", "趋势", "发展", "latest", "new", "trend", "development",
            # 教程指南
            "怎么做", "如何", "教程", "指南", "how to", "tutorial", "guide", "步骤"
        ]
        
        # 检查是否包含任何搜索关键词
        if any(keyword in user_input_lower for keyword in search_keywords):
            return {
                "query": user_input.strip(),
                "description": "智能搜索",
                "confidence": 0.8
            }
        
        return None


    async def _handle_generate_code_stream(self, user_input: str, session_id: str):
        """处理代码生成命令 - 流式分段输出的智能迭代调试流程"""
        # 提取代码生成需求和可选的文件名
        parts = user_input.replace("/generate_code", "").strip().split(" 保存为 ")
        requirement = parts[0].strip()
        custom_filename = parts[1].strip() if len(parts) > 1 else None
        
        if not requirement:
            yield """请描述您想要生成的代码功能，例如：
/generate_code 创建一个计算斐波那契数列的函数
/generate_code 写一个简单的网页爬虫 保存为 web_crawler.py
/generate_code 实现一个基础的计算器类
/generate_code 生成一个有bug的排序算法用于调试演示"""
            return

        try:
            if not self.llm:
                yield "❌ LLM服务不可用，无法生成代码"
                return
            
            yield f"🎯 开始智能代码生成流程...\n\n📝 需求：{requirement}\n\n"
            
            # === 第一阶段：AI生成初始代码 ===
            yield "🤖 === AI代码生成阶段 ===\n"
            yield "🔄 正在生成代码...\n"
            
            code_prompt = f"""请根据以下需求生成Python代码：

需求：{requirement}

请生成完整的、可运行的Python代码，包括：
1. 必要的导入语句
2. 完整的函数或类实现
3. 简单的使用示例或测试代码
4. 适当的注释说明

请直接返回代码，不需要额外的解释文字。"""

            current_code = await self.llm.chat(code_prompt)
            yield "✅ AI代码生成完成！\n\n"
            yield f"📋 生成的代码：\n```python\n{current_code}\n```\n\n"
            
            # === 生成智能文件名 ===
            yield "📁 === 文件命名阶段 ===\n"
            yield "🔄 正在生成智能文件名...\n"
            
            if custom_filename:
                filename = custom_filename if custom_filename.endswith('.py') else f"{custom_filename}.py"
                yield f"✅ 使用自定义文件名：{filename}\n\n"
            else:
                filename_prompt = f"""请为以下Python代码生成一个合适的文件名：

代码功能：{requirement}

代码内容：
{current_code[:500]}...

请生成一个简洁、描述性的Python文件名（不超过30个字符，使用英文和下划线），例如：
- fibonacci_calculator.py
- web_scraper.py
- calculator_class.py

只返回文件名，不要其他内容。"""

                filename = (await self.llm.chat(filename_prompt)).strip()
                if not filename.endswith('.py'):
                    filename += '.py'
                yield f"✅ AI生成文件名：{filename}\n\n"
            
            # 生成本地文件名（带时间戳）
            import time
            timestamp = int(time.time())
            local_filename = f"generated_code_{timestamp}.py"
            
            # === 第二阶段：代码测试与调试 ===
            yield "🧪 === 代码测试阶段 ===\n"
            yield "🔄 正在执行代码测试...\n"
            
            # 保存代码到临时文件进行测试
            import os
            # 使用相对路径，避免与 FileTool 的 workspace_dir 重复拼接
            # FileTool 已经设置了 workspace_dir="/workspace"，所以这里使用相对路径
            uploads_dir = "uploads"
            temp_dir = "temp"
            
            # 确保目录存在（使用 FileTool 的方式）
            # FileTool 会自动处理完整路径的创建
            
            # 使用相对路径存放测试文件
            temp_path = f"{temp_dir}/{local_filename}"
            self.file_tool.write_file(temp_path, current_code)
            yield f"💾 代码已保存到临时文件：{temp_path}\n"
            
            # 执行代码测试
            import subprocess
            import sys
            
            max_iterations = 3  # 最大调试迭代次数
            iteration = 1
            
            while iteration <= max_iterations:
                yield f"\n🔄 第 {iteration} 轮测试...\n"
                
                try:
                    # 执行代码 - 需要使用完整路径和正确的工作目录
                    full_temp_path = os.path.join(self.file_tool.workspace_dir, temp_path)
                    result = subprocess.run(
                        [sys.executable, full_temp_path],
                        capture_output=True,
                        text=True,
                        timeout=30,
                        cwd=self.file_tool.workspace_dir  # 设置正确的工作目录
                    )
                    
                    if result.returncode == 0:
                        # 代码执行成功
                        yield "✅ 代码执行成功！\n"
                        if result.stdout:
                            yield f"📤 输出结果：\n{result.stdout}\n"
                        break
                    else:
                        # 代码执行失败，需要调试
                        error_info = result.stderr or "未知错误"
                        yield f"❌ 代码执行失败\n"
                        yield f"🐛 错误信息：\n{error_info}\n"
                        
                        if iteration >= max_iterations:
                            yield f"⚠️ 已达到最大调试次数，保存当前版本\n"
                            break
                        
                        # AI分析和修复代码
                        yield f"🔍 === AI调试分析阶段 ===\n"
                        yield f"🤖 正在分析错误原因...\n"
                        
                        debug_prompt = f"""请分析以下Python代码中的问题并提供修复建议：

原始需求：{requirement}

当前代码：
```python
{current_code}
```

错误信息：
{error_info}

请提供：
1. **问题分析**：详细说明错误的具体原因和类型
2. **修复方案**：提供具体的修复步骤和建议
3. **修复后的完整代码**：提供修复后的完整可运行代码

请用中文回答，格式清晰。在问题分析部分要详细说明问题的根本原因。"""

                        debug_response = await self.llm.chat(debug_prompt)
                        yield "✅ 问题分析完成\n\n"
                        
                        # 显示AI的问题分析
                        if "问题分析" in debug_response or "错误" in debug_response:
                            # 提取问题分析部分
                            analysis_start = debug_response.find("问题分析")
                            if analysis_start == -1:
                                analysis_start = 0
                            
                            # 查找修复方案的开始位置
                            fix_start = debug_response.find("修复方案")
                            if fix_start == -1:
                                fix_start = debug_response.find("修复")
                            
                            if fix_start > analysis_start:
                                analysis_text = debug_response[analysis_start:fix_start].strip()
                            else:
                                # 如果没找到修复方案，取前半部分作为分析
                                analysis_text = debug_response[:len(debug_response)//2].strip()
                            
                            yield f"🔍 **AI问题分析**：\n{analysis_text}\n\n"
                        
                        # 提取优化后的代码
                        if "```python" in debug_response:
                            import re
                            code_blocks = re.findall(r'```python\n(.*?)\n```', debug_response, re.DOTALL)
                            if code_blocks:
                                current_code = code_blocks[-1]  # 取最后一个代码块
                                yield f"🛠️ === 系统优化阶段 ===\n"
                                yield "✅ 代码优化完成\n"
                                yield f"📋 优化后的代码：\n```python\n{current_code}\n```\n\n"
                                
                                # 保存优化后的代码
                                self.file_tool.write_file(temp_path, current_code)
                            else:
                                yield "⚠️ 未能提取到优化后的代码，使用原代码继续\n\n"
                        else:
                            yield "⚠️ AI未提供代码块格式的优化代码，使用原代码继续\n\n"
                
                except subprocess.TimeoutExpired:
                    yield f"⏰ 代码执行超时（30秒），可能存在无限循环\n"
                    if iteration >= max_iterations:
                        break
                    yield f"🔍 正在分析超时问题...\n"
                    # 这里可以添加超时问题的特殊处理
                except Exception as e:
                    yield f"❌ 执行过程中发生异常：{str(e)}\n"
                    break
                
                iteration += 1
            
            # 如果达到最大迭代次数仍未成功
            if iteration > max_iterations:
                yield f"⚠️ 已达到最大优化次数({max_iterations}次)，保存当前最优版本\n\n"
            
            # === 保存最终版本到会话文件管理 ===
            yield "💾 === 文件保存阶段 ===\n"
            
            # 将最终代码保存到会话文件管理器中（这是用户可以管理的文件）
            try:
                file_content_bytes = current_code.encode('utf-8')
                file_info = self.upload_manager.save_uploaded_file(session_id, filename, file_content_bytes)
                yield f"✅ 文件已保存到会话文件管理器\n"
                yield f"   - 显示名称：{filename}\n"
                yield f"   - 文件ID：{file_info['id']}\n"
                yield f"   - 文件路径：{file_info['file_path']}\n"
            except Exception as e:
                yield f"❌ 文件保存失败: {str(e)}\n"
            
            # === 最终结果展示 ===
            yield f"\n🎯 === 流程完成 ===\n"
            yield f"📁 最终文件：{filename}\n"
            yield f"🔄 优化轮次：{iteration-1}轮\n"
            yield f"📋 最终代码：\n```python\n{current_code}\n```\n\n"
            
            # 操作提示
            yield f"💡 后续操作：\n"
            yield f"- 使用 `/read {filename}` 查看完整代码\n"
            yield f"- 使用 `/run_code {filename}` 直接运行代码\n"
            yield f"- 使用 `/debug_code {filename}` 调试代码\n"
            yield f"- 通过前端文件管理器查看和管理 {filename}\n"
            
            # 清理临时文件
            yield f"\n🧹 正在清理临时文件...\n"
            try:
                # 使用完整路径进行清理
                full_temp_path = os.path.join(self.file_tool.workspace_dir, temp_path)
                if os.path.exists(full_temp_path):
                    os.remove(full_temp_path)
                    yield f"✅ 已清理临时文件：{temp_path}\n"
                else:
                    yield f"ℹ️ 临时文件不存在，无需清理：{temp_path}\n"
            except Exception as e:
                yield f"⚠️ 清理临时文件失败：{str(e)}\n"
                
        except Exception as e:
            yield f"❌ 智能代码生成流程失败：{str(e)}"
            # 即使出错也要尝试清理临时文件
            try:
                if 'temp_path' in locals():
                    full_temp_path = os.path.join(self.file_tool.workspace_dir, temp_path)
                    if os.path.exists(full_temp_path):
                        os.remove(full_temp_path)
                        yield f"🧹 已清理临时文件\n"
            except:
                pass

    
    async def _auto_debug_code(self, filepath: str, code_content: str, error_info: str, session_id: str) -> str:
        """自动调试代码的内部函数"""
        try:
            # 构建调试分析提示
            debug_prompt = f"""请分析以下Python代码中的问题并提供修复建议：

文件：{filepath}

代码内容：
```python
{code_content}
```

错误信息：
{error_info}

请提供：
1. 问题分析：识别错误类型和具体问题
2. 修复建议：提供具体的修复方案
3. 修复后的完整代码（如果可以修复的话）

请用中文回答，格式清晰。"""

            if self.llm:
                debug_analysis = await self.llm.chat(debug_prompt)
                
                # 尝试提取修复后的代码并保存
                if "```python" in debug_analysis:
                    import re
                    code_blocks = re.findall(r'```python\n(.*?)\n```', debug_analysis, re.DOTALL)
                    if code_blocks:
                        fixed_code = code_blocks[-1]  # 取最后一个代码块
                        
                        # 保存修复后的代码
                        fixed_filename = filepath.replace('.py', '_fixed.py')
                        self.file_tool.write_file(fixed_filename, fixed_code)
                        
                        # 将修复后的代码也注册到文件管理器
                        try:
                            import os
                            original_filename = os.path.basename(fixed_filename)
                            file_content_bytes = fixed_code.encode('utf-8')
                            file_info = self.upload_manager.save_uploaded_file(session_id, original_filename, file_content_bytes)
                            debug_analysis += f"\n\n🔧 修复后的代码已保存到：{fixed_filename}"
                            debug_analysis += f"\n✅ 修复后的文件已注册到文件管理器，ID: {file_info['id']}"
                            debug_analysis += f"\n💡 使用 /run_code {fixed_filename} 测试修复结果"
                        except Exception as e:
                            debug_analysis += f"\n\n🔧 修复后的代码已保存到：{fixed_filename}"
                            debug_analysis += f"\n⚠️ 文件管理器注册失败: {str(e)}"
                            debug_analysis += f"\n💡 使用 /run_code {fixed_filename} 测试修复结果"
                
                return f"🤖 AI调试分析：\n{debug_analysis}\n"
            else:
                return "❌ LLM服务不可用，无法进行自动调试\n"
                
        except Exception as e:
            return f"❌ 自动调试失败：{str(e)}\n"

    def _handle_run_code(self, user_input: str, session_id: str) -> str:
        """处理代码执行命令 - 支持通过文件名自动拼接会话上传路径"""
        # 提取文件名
        filename = user_input.replace("/run_code", "").strip()
        
        if not filename:
            return """请指定要执行的Python文件名，例如：
/run_code climb_stairs_dp.py
/run_code my_script.py
/run_code calculator.py"""

        try:
            import subprocess
            
            # 构建会话上传目录的文件路径
            session_upload_dir = self.upload_manager.get_session_upload_dir(session_id)
            
            # 首先尝试直接使用文件名
            full_path = os.path.join(session_upload_dir, filename)
            
            # 如果直接文件名不存在，尝试通过原始文件名查找UUID文件名
            if not os.path.exists(full_path):
                # 获取会话中的所有文件信息
                session_files = self.upload_manager.get_session_files(session_id)
                found_file = None
                
                for file_info in session_files:
                    # 检查原始文件名是否匹配
                    if file_info.get('original_name') == filename:
                        found_file = file_info
                        break
                
                if found_file:
                    # 使用找到的UUID文件名
                    full_path = os.path.join(session_upload_dir, found_file['saved_name'])
                else:
                    # 列出当前会话的所有文件
                    if session_files:
                        file_list = "\n".join([f"- {f.get('original_name', f.get('saved_name', 'unknown'))}" for f in session_files])
                        return f"❌ 文件不存在：{filename}\n\n📁 当前会话中的文件：\n{file_list}\n\n💡 使用 /uploads 查看详细信息"
                    else:
                        return f"❌ 文件不存在：{filename}\n💡 当前会话中没有上传的文件"
            
            # 执行Python代码
            # 获取实际的文件名（可能是UUID格式）
            actual_filename = os.path.basename(full_path)
            result = subprocess.run(
                ["python", actual_filename],
                capture_output=True,
                text=True,
                timeout=30,  # 30秒超时
                cwd=session_upload_dir
            )
            
            output = ""
            if result.stdout:
                output += f"📤 标准输出：\n{result.stdout}\n"
            
            if result.stderr:
                output += f"❌ 错误输出：\n{result.stderr}\n"
            
            if result.returncode == 0:
                return f"""✅ 代码执行成功！

📁 执行文件：{filename}
🔢 返回码：{result.returncode}

{output}

💡 提示：如果有错误，可以使用 /debug_code {filename} 来获取调试建议"""
            else:
                return f"""❌ 代码执行失败！

📁 执行文件：{filename}
🔢 返回码：{result.returncode}

{output}

🔧 建议：使用 /debug_code {filename} 来分析和修复错误"""
                
        except subprocess.TimeoutExpired:
            return f"⏰ 代码执行超时（30秒），可能存在无限循环或长时间运行的操作"
        except Exception as e:
            return f"❌ 执行代码时出错：{str(e)}"

    async def _handle_debug_code(self, user_input: str, session_id: str) -> str:
        """处理代码调试命令 - 支持通过文件名自动拼接会话上传路径"""
        # 提取文件名
        filename = user_input.replace("/debug_code", "").strip()
        
        if not filename:
            return """请指定要调试的Python文件名，例如：
/debug_code climb_stairs_dp.py
/debug_code my_script.py
/debug_code calculator.py"""

        try:
            # 构建会话上传目录的文件路径
            session_upload_dir = self.upload_manager.get_session_upload_dir(session_id)
            full_path = os.path.join(session_upload_dir, filename)

            # 检查文件是否存在
            if not os.path.exists(full_path):
                # 如果直接路径不存在，尝试通过原始文件名查找UUID文件名
                session_files = self.upload_manager.get_session_files(session_id)
                found_file = None
                
                for file_info in session_files:
                    if file_info.get('original_name') == filename:
                        found_file = file_info
                        break
                
                if found_file:
                    # 使用找到的UUID文件名
                    full_path = os.path.join(session_upload_dir, found_file['saved_name'])
                else:
                    # 文件确实不存在，提供友好的错误信息
                    file_list = [f"- {f.get('original_name', f.get('saved_name', 'unknown'))}" for f in session_files]
                    files_info = "\n".join(file_list) if file_list else "  (当前会话没有文件)"
                    
                    return f"""❌ 文件不存在：{filename}

📁 当前会话中的文件：
{files_info}

💡 使用 /uploads 查看详细的文件信息"""
            
            # 直接读取文件内容
            with open(full_path, 'r', encoding='utf-8') as f:
                code_content = f.read()
            
            # 先尝试执行代码获取错误信息
            import subprocess
            execution_result = ""
            
            try:
                # 获取实际的文件名（可能是UUID格式）
                actual_filename = os.path.basename(full_path)
                result = subprocess.run(
                    ["python", actual_filename],
                    capture_output=True,
                    text=True,
                    timeout=10,
                    cwd=session_upload_dir
                )
                
                if result.stderr:
                    execution_result = f"执行错误：\n{result.stderr}"
                elif result.returncode != 0:
                    execution_result = f"程序异常退出，返回码：{result.returncode}"
                else:
                    execution_result = "代码执行成功，无明显错误"
                    
            except subprocess.TimeoutExpired:
                execution_result = "代码执行超时，可能存在无限循环"
            except Exception as e:
                execution_result = f"执行测试失败：{str(e)}"
            
            # 构建调试分析提示
            debug_prompt = f"""请分析以下Python代码中的问题并提供修复建议：

文件：{filename}

代码内容：
```python
{code_content}
```

执行结果：
{execution_result}

请提供：
1. 问题分析：识别代码中的错误类型（语法错误、逻辑错误、运行时错误等）
2. 具体问题：指出问题所在的行和原因
3. 修复建议：提供具体的修复方案
4. 改进建议：提供代码优化和最佳实践建议
5. 修复后的完整代码

请用中文回答，格式清晰易读。"""

            # 使用LLM进行调试分析
            if self.llm:
                debug_analysis = await self.llm.chat(debug_prompt)
                
                return f"""🔍 代码调试分析

📁 文件：{filename}

🔧 执行测试结果：
{execution_result}

🤖 AI调试分析：
{debug_analysis}

💡 调试提示：
- 仔细检查语法错误（缩进、括号匹配等）
- 验证变量名拼写和作用域
- 检查逻辑流程和边界条件
- 确保导入的模块已安装

🛠️ 下一步操作：
- 根据分析修改代码
- 使用 /run_code {filename} 重新测试"""
            else:
                return f"""🔍 基础调试信息

📁 文件：{filename}

🔧 执行测试结果：
{execution_result}

📋 代码内容：
```python
{code_content}
```

❌ LLM服务不可用，无法提供详细的调试分析

💡 手动调试建议：
1. 检查语法错误（缩进、括号、引号匹配）
2. 验证变量名和函数名拼写
3. 确认导入的模块是否正确
4. 检查逻辑流程和条件判断
5. 验证数据类型和边界条件"""
                
        except Exception as e:
            return f"❌ 调试分析失败：{str(e)}"
